/**
 * author: 潘毅
 * email: pye-mail@163.com
 * date: 2016-03-30 11:27:32
 * remark: 模块化基础类
 */

//(注意)严格模式
"use strict";

/**
 * BaseModule(模块)
 * @param  {Object} setting配置参数对象
 * @param  {Object} 子作用域中可访问的私有方法对象
 * @return {Object} 对外接口方法(可通过原型，实现自定义公共方法)
 */
var BaseModule = function(setting, childScope){

	var self = this;

	//事件委托对象
	childScope.Delegates = {};
	//存储自定义委托对象
	var customDelegates = {},
		//存储自定义[defineProperty]对象
		customDefineProperty = {},
		//存储[defineProperty]的存储状态对象
		definePropertyStatus = [],
		//存储自定义setter和getter操作对象
		customObject = null,
		//是否支持[defineProperty]
		isDefineProperty = (function(){
			var boolean = true;
			try {
				Object.defineProperty({}, '', {set: function(){}, get: function(){}});
			} catch(e) {
				boolean = false;
			}
			return boolean;
		})(),
		keyAll = '__[ALL]__',
		byObject = '->object';

	/**
	 * 定义属性的setter和getter
	 * @param  {Object} options 参数对象
	 * @return {Object} 当前实例对象
	 */
	var defineProperty = function(options){
		var propertyObj = {
			//作用的对象
			obj: options.obj || customObject || setting,
			//作用对象中的属性名称
			name: options.name,
			//getter操作
			getterHandler: options.getterHandler,
			//setter操作
			setterHandler: options.setterHandler
		};
		var name = propertyObj.name;

		//获取缓存中已存在的对象
		var thisProperty = customDefineProperty[name];
		if(thisProperty){
			//如果缓存中已存在，替换为本次提供的参数
			for(var key in propertyObj){
				if(propertyObj[key]){
					customDefineProperty[name][key] = propertyObj[key];
				}
			}
		}
		else{
			//缓存中不存在，直接保存为缓存
			customDefineProperty[name] = propertyObj;
		}

		return self;
	};

	/**
	 * 渲染属性的setter和getter
	 * @param  {String} type  setter或getter类型
	 * @param  {Object} obj   属性所属对象
	 * @param  {String} name  属性名称
	 * @param  {Object} value 属性值
	 * @return {Object}       getter后的值
	 */
	var renderProperty = function(type, obj, name, value, idx){
		//获取缓存中当前要操作的对象
		var propertyObject = customDefineProperty[name],
			//setter操作对象
			setterHandler,
			//getter操作对象
			getterHandler;			

		if(propertyObject){
			//如果缓存中存在需要操作的数据，表示已经定义了对obj指定的[name]属性的setter和getter操作
			setterHandler = propertyObject.setterHandler;
			getterHandler = propertyObject.getterHandler;
			/*try{
				if(!definePropertyStatus[name]){
					if(type == 'getter'){
						if(!getterHandler){
							return;
						}
					}
					else if(type == 'setter'){
						if(!setterHandler){
							return;
						}
					}
					//未做过defineProperty处理过，切浏览器支持原生方式[Object.defineProperty]的操作
					Object.defineProperty(obj, name, {
						//getter操作
						get: (function(getterHandler, name, value){
							return function(){
								var result;
								if(getterHandler)
									//执行自定义getter操作
									result = getterHandler.call(this, value, name);
								return result || value;
							};
						})(getterHandler, name, value),
						//setter操作
						set: (function(setterHandler, name){
							return function(newValue){
								if(setterHandler){
									//执行自定义setter操作
									setterHandler.call(this, newValue, name);
								}
							};
						})(setterHandler, name)
					});
					//将当前[name]属性标记为已处理状态
					definePropertyStatus[name] = true;
				}
			}
			catch(e){*/
				//表示浏览器不支持[Object.defineProperty]，则以自定义实现方式进行setter和getter操作
				if(type == 'setter'){
					if(setterHandler){
						if(idx != undefined){
							return setterHandler.call(obj, value, idx, name);
						}
						else{
							return setterHandler.call(obj, value, name);
						}
					}
				}
				else if(type == 'getter'){
					if(getterHandler){
						if(idx != undefined){
							return getterHandler.call(obj, value, idx, name);
						}
						else{
							return getterHandler.call(obj, value, name);
						}
					}
				}
			//}
		}
		else {
			//表示缓存中未定义对obj指定的[name]属性的setter和getter操作
			//这时有两种情况：1.确实没有定义 
			//2.定义了对obj对象所有属性的setter和getter操作，这时在缓存中则会存在一个[__[ALL]__]的对象
			var allDefineProperty = customDefineProperty[keyAll];
			if(allDefineProperty){
				if(type == 'setter'){
					setterHandler = allDefineProperty.setterHandler;
					if(setterHandler){
						if(idx != undefined){
							return setterHandler.call(obj, value, idx, name);
						}
						else{
							return setterHandler.call(obj, value, name);
						}
					}
				}
				else if(type == 'getter'){
					getterHandler = allDefineProperty.getterHandler;
					if(getterHandler){
						if(idx != undefined){
							return getterHandler.call(obj, value, idx, name);
						}
						else{
							return getterHandler.call(obj, value, name);
						}
					}
				}
			}
		}
	};

	/**
	 * 绑定自定义事件
	 * @param  {String} name 事件名称
	 * @param  {Function} handler 事件函数
	 * @return {Object} 当前实例对象
	 */
	childScope.Delegates.on = function(name, handler){
		if(name && handler)
			customDelegates['on'+name] = handler;
		return self;
	};

	/**
	 * 触发(执行或响应)已绑定的自定义事件
	 * @param  {String} name 事件名称
	 * @param  {Array} args 需要传递给事件函数的参数集合
	 * @param  {object} posing 以对象冒充的方式替换事件函数this
	 * @return {Object} 事件返回值或当前实例对象
	 */
	childScope.Delegates.fire = function(name, args, posing){
		var handler = customDelegates['on'+name];
		return handler ? handler.apply(posing || self, args || []) : self;
	};

	/**
	 * 移除事件监听
	 * @param  {String} name 事件名称
	 * @return {Object} 当前实例对象
	 */
	childScope.Delegates.shift = function(name){
		if(name)
			customDelegates['on'+name] = undefined;
		else
			customDelegates = {};
		return self;
	};

	/**
	 * 设置自定义setter和getter操作对象
	 * @param  {Object} obj 自定义setter和getter的操作对象
	 * @return {Object} 当前实例对象
	 */
	self.by = function(obj){
	    //保存自定义setter和getter操作对象
	    customObject = obj;
	    return self;
	};

	/**
	 * 还原操作对象Object
	 * @param  {[type]} args [description]
	 * @return {Object} 当前实例对象
	 */
	self.restore = function(){
	    //还原对object的操作对象
	    customObject = undefined;
	    return self;
	};

	/**
	 * 对象合并(支持深度检测，包括JSON对象和Array对象)
	 * @param  {Object} options 参数集合对象
	 * @return {Object} 合并后的对象
	 */
	/*self.merge = function(options){
		options = {
			//深度检测
			bool: options.bool != undefined && options.bool != null ? options.bool : false,
			//合并到新对象
			dest: options.dest,
			//合并对象集合
			src: options.src,
			//嵌套对象的key串联字符串
			key: options.key
		};
		var optionsKey = options.key;
		var objString = Object.prototype.toString.call(options.src).toLowerCase();
		if(objString == '[object object]'){
			options.src = [options.src];
		}
		var src = options.src;
		var i = 0, len = src.length, item, value, flag = true;
		if(!options.dest){
			options.dest = options.src[0];
			i = 1;
			flag = false;
		}
		for(;i<len;i++){
			item = src[i];
			objString = Object.prototype.toString.call(item).toLowerCase();
			if(objString == '[object object]'){
				for(var key in item){
					value = item[key];
					objString = Object.prototype.toString.call(value).toLowerCase();
					if((objString == '[object object]' || objString == '[object array]') && options.bool){
						objString = Object.prototype.toString.call(options.dest[key]).toLowerCase();
						if(objString != '[object object]' && objString != '[object array]'){
							options.dest[key] = value;
						}
						else{
							value = self.merge({
								bool: options.bool,
								dest: options.dest[key],
								src: [value],
								key: optionsKey ? (optionsKey+'.'+key) : key
							});
						}
					}
					if(flag){
						if(optionsKey){
							self.set(optionsKey+'.'+key, value);
						}
						options.dest[key] = value;
					}
					else{
						self.set(key, value);
					}
				}
			}
			else if(objString == '[object array]'){
				var j = 0, itemLen = item.length;
				for(;j<itemLen;j++){
					value = item[j];
					objString = Object.prototype.toString.call(value).toLowerCase();
					if((objString == '[object object]' || objString == '[object array]') && options.bool){
						value = self.merge({
							bool: options.bool,
							dest: options.dest[j],
							src: [value],
							key: optionsKey
						});
					}
					options.dest[j] = value;
				}
			}
			if(flag){
				flag = false;
			}
		}
		return options.dest;
	};*/

	/**
	 * 设置属性
	 * @param {String/Object} key 需要设置的键名，也可以是一个键值对的对象
	 * @param {String} val 需要设置键的值
	 * @return {Object} 当前实例对象
	 */
    self.set = function(key, val){
		var setterValue,
			obj = customObject || setting;
		if(typeof(key) == 'object'){
			//设置多个值
			var newValue;
			for(var temp in key){
				newValue = key[temp];
				obj[temp] = key[temp];
				setterValue = renderProperty('setter', obj, temp, newValue);
				obj[temp] = setterValue || key[temp];
			}
		}
		else{			
			var objString = Object.prototype.toString.call(val).toLowerCase();
			if(objString === '[object array]'){
				var tempAry = [];
				var i = 0, len = val.length, item;
				for(;i<len;i++){
					item = val[i];
					setterValue = renderProperty('setter', obj, key, item, i);
					tempAry.push(setterValue||item);
				}				
				setterValue = renderProperty('setter', obj, key+byObject, tempAry);
				obj[key] = setterValue || tempAry;
			}
			else{
				//设置单个指定的值
				if(key.indexOf('.')>-1){
					var keyAry = key.split('.'), tempObj;
					var i = 0, len = keyAry.length, item;
					for(;i<len;i++){
						item = keyAry[i];
						if(tempObj){
							tempObj = (function(){
								if(i == len-1){
									if(!tempObj){
										tempObj = {};
									}
									setterValue = renderProperty('setter', obj, key, val);
									try {
										tempObj[item] = setterValue || val;
									} catch(exception) {
									}
								}
								return tempObj[item];
							})();
						}
						else{
							tempObj = obj[item];
						}
					}
				}
				else{
					obj[key] = val;
					setterValue = renderProperty('setter',obj, key, val);
					obj[key] = setterValue || val;
				}
			}
		}
		
		return self;
    };

	/**
    * 获取属性
    * @param  {Object} key 需要获取属性的Key值，也可以是一组获取多个属性的集合对象
    * @return {Object} 获取到的属性对象或集合[{name: '属性Key名称', value: '属性对应值', disabled: '禁用还是非禁用'}]
    */
    self.get = function(key){
		var result = [], 
			getterValue, 
			value,
			obj = customObject || setting;
		
		if(typeof(key) == 'object'){
			var objString = Object.prototype.toString.call(key).toLowerCase();
			if(objString === '[object array]'){
				//如果key传入的是一个数组集合，表示需要获取多个属性值，将返回一个获取值得集合
				var i = 0, len = key.length, item;
				for(;i<len;i++){
					item = key[i];
					value = obj[item];
					getterValue = renderProperty('getter', obj, item, value);
					result.push({name: item, value: getterValue || value });
				}
			}
			else if(objString == '[object object]'){
				//如果key传入的是一个键值对对象，同样是获取多个值
				for(var i in key){
					value = obj[i];
					getterValue = renderProperty('getter', obj, i, value);
					result.push({name: i, value: getterValue || value });
				}
			}
		}
		else if(typeof(key) == 'string'){
			//获取单个值
			if(key.indexOf('.')>-1){
				var keyAry = key.split('.');
				var i = 0, len = keyAry.length, item;
				for(;i<len;i++){
					item = keyAry[i];
					if(value){
						value = value[item];
					}
					else{
						value = obj[item];
					}
				}
			}
			else{
				value = obj[key];
			}			
			var objString = Object.prototype.toString.call(value).toLowerCase();
			if(objString === '[object array]'){
				var tempAry = [];
				var i = 0, len = value.length, item;
				for(;i<len;i++){
					item = value[i];
					getterValue = renderProperty('getter', obj, key, item, i);
					tempAry.push(getterValue||item);
				}
				getterValue = renderProperty('getter', obj, key+byObject, tempAry);
				result = {name: key, value: getterValue || tempAry };
			}
			else{
				getterValue = renderProperty('getter', obj, key, value);
				result = {name: key, value: getterValue || value };
			}
		}

		result = result.value ? result.value : ((result.name && !result.value) ? undefined : result);

		return result;
	};

    /**
	 * (手动执行)渲染
	 * @param {Function} callBack 渲染回调函数
	 */
    self.render = function(callBack){
    	//渲染模板
    	childScope.render(function(node){
    		childScope.bindEvent();
    		if(callBack && typeof(callBack) == 'function')
    			callBack.call(node);
    	});
    	return self;
    };

    /**
     * 添加组件事件委托
     * @param  {String} name 委托事件名称
     * @param  {Function} handler 事件操作函数
     * @return {Object} 当前实例对象
     */
    self.on = function(name, handler){
    	if(handler){
    		//委托事件
    		childScope.Delegates.on(name, handler);
    	}
    	else{
    		//触发事件
    		childScope.Delegates.fire(name, null, setting.templateNode);
    	}

    	return self;
    };

    /**
	 * 移除事件监听
	 * @param  {String} name 事件名称
	 * @return {Object} 当前实例对象
	 */
	self.shift = function(name){
		return childScope.Delegates.shift(name);
	};

    /**
	 * 定义属性的setter和getter
	 * @param  {Object} options 参数对象
	 * @return {Object} 当前实例对象
	 */
    self.defineProperty = function(options){
    	//保存定义的setter和getter操作
    	options.name = options.name || keyAll;
		options.obj = customObject || setting;
    	defineProperty(options);
    };

    /**
     * 给指定属性设置setter操作
     * @param  {String} name    属性名称
     * @param  {Function} handler 属性的setter操作函数
     * @return {Object}         当前实例对象
     */
    self.setter = function(name, handler, handlerFn){
		var obj = customObject || setting;
    	var typeOfName = typeof(name);
    	if(typeOfName == 'function'){
    		handler = name;
    		name = null;
    	}    	
    	var defineHandlerFn = function(obj, name, handler){
    		//定义一个返回数组整体对象的hander
	    	defineProperty({
	    		obj: obj,
	    		name: name,
	    		setterHandler: handler
	    	});
    	};
    	if(name){
    		//如果指定了[name]，表示对setting对象中指定属性设置了setter操作
    		if(typeOfName == 'string'){
    			//设置单个
		    	defineProperty({
		    		obj: obj,
		    		name: name,
		    		setterHandler: handler
		    	});
		    	if(handlerFn){
		    		defineHandlerFn(obj, name+byObject, handlerFn);
		    	}
		    }
		    else if(typeOfName == 'object'){
		    	//设置一个数组集合(多个)
		    	var i = 0, len = name.length || 0, item;
		    	for(;i<len;i++){
		    		item = name[i];
		    		defineProperty({
			    		obj: obj,
			    		name: item,
			    		setterHandler: handler
			    	});
			    	if(handlerFn){
			    		defineHandlerFn(obj, item+byObject, handlerFn);
			    	}
		    	}
		    }
	    }
	    else{
	    	//如果未指定对应的setting属性，表示对setting对象中的所有属性设置setter操作(包括开始不存在，后面加上的属性)
	    	//并设置一个特殊缓存对象[__[ALL]__]，用于标识是针对所有属性的操作
	    	if(obj){
	    		//设置全部
	    		for(var key in obj){
	    			defineProperty({
			    		obj: obj,
			    		name: key,
			    		setterHandler: handler
			    	});
			    	if(handlerFn){
			    		defineHandlerFn(obj, key+byObject, handlerFn);
			    	}
	    		}
	    		defineProperty({
		    		obj: obj,
		    		name: keyAll,
		    		setterHandler: handler
		    	});
		    	if(handlerFn){
		    		defineHandlerFn(obj, keyAll+byObject, handlerFn);
		    	}
	    	}
	    }

    	return self;
    };

    /**
     * 给指定属性设置getter操作
     * @param  {String} name    属性名称
     * @param  {Function} handler 属性的getter操作函数
     * @return {Object}         当前实例对象
     */
    self.getter = function(name, handler, handlerFn){
		var obj = customObject || setting;
    	var typeOfName = typeof(name);
    	if(typeOfName == 'function'){
    		handler = name;
    		name = null;
    	}
    	var defineHandlerFn = function(obj, name, handler){
    		//定义一个返回数组整体对象的hander
	    	defineProperty({
	    		obj: obj,
	    		name: name,
	    		getterHandler: handler
	    	});
    	};
    	if(name){
    		//如果指定了[name]，表示对setting对象中指定属性设置了getter操作
    		if(typeOfName == 'string'){
    			//设置单个
		    	defineProperty({
		    		obj: obj,
		    		name: name,
		    		getterHandler: handler
		    	});
			    if(handlerFn){
			    	//定义一个返回数组整体对象的hander
			    	defineHandlerFn(obj, name+byObject, handlerFn);
			    }
		    }
		    else if(typeOfName == 'object'){
		    	//设置一个数组集合(多个)
		    	var i = 0, len = name.length || 0, item;
		    	for(;i<len;i++){
		    		item = name[i];
		    		defineProperty({
			    		obj: obj,
			    		name: item,
			    		getterHandler: handler
			    	});
				    if(handlerFn){
				    	//定义一个返回数组整体对象的hander
				    	defineHandlerFn(obj, item+byObject, handlerFn);
				    }
		    	}
		    }
	    }
	    else{
	    	//如果未指定对应的setting属性，表示对setting对象中的所有属性设置getter操作(包括开始不存在，后面加上的属性)
	    	//并设置一个特殊缓存对象[__[ALL]__]，用于标识是针对所有属性的操作
	    	if(obj){
	    		//设置全部
	    		for(var key in obj){
	    			defineProperty({
			    		obj: obj,
			    		name: key,
			    		getterHandler: handler
			    	});
				    if(handlerFn){
				    	//定义一个返回数组整体对象的hander
				    	defineHandlerFn(obj, key+byObject, handlerFn);
				    }
	    		}
	    		defineProperty({
		    		obj: obj,
		    		name: keyAll,
		    		getterHandler: handler
		    	});
			    if(handlerFn){
			    	//定义一个返回数组整体对象的hander
			    	defineHandlerFn(obj, keyAll+byObject, handlerFn);
			    }
	    	}
	    }

    	return self;
    };
};


//输出(接口)
module.exports = BaseModule;